package camera;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.Manifest;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.Fragment;
import android.content.Context;
import android.content.DialogInterface;
import android.media.MediaRecorder;
import android.os.Build;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.RectF;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.StreamConfigurationMap;

import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.util.Log;
import android.util.Range;
import android.util.Size;
import android.util.SparseIntArray;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.Toast;

import java.io.FileDescriptor;
import java.util.List;

import android.util.SparseIntArray;
import android.widget.ImageView;
import android.media.Image;
import android.media.ImageReader;
import android.view.TextureView;
//import androidx.annotation.NonNull;
//import androidx.appcompat.app.AppCompatActivity;
//import androidx.core.content.ContextCompat;
//import androidx.constraintlayout.widget.Group;

import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;


import net.majorkernelpanic.spydroid.ui.SpydroidActivity;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

public class Camera {
	private static final int SENSOR_ORIENTATION_DEFAULT_DEGREES = 90;
	private static final int SENSOR_ORIENTATION_INVERSE_DEGREES = 270;
	private static final SparseIntArray DEFAULT_ORIENTATIONS = new SparseIntArray();
	private static final SparseIntArray INVERSE_ORIENTATIONS = new SparseIntArray();

	private static final String TAG = "Camera2VideoFragment";
	private static final int REQUEST_VIDEO_PERMISSIONS = 1;
	private static final String FRAGMENT_DIALOG = "dialog";

	private static final String[] VIDEO_PERMISSIONS = {
			Manifest.permission.CAMERA,
			Manifest.permission.RECORD_AUDIO,
	};

	static {
		DEFAULT_ORIENTATIONS.append(Surface.ROTATION_0, 90);
		DEFAULT_ORIENTATIONS.append(Surface.ROTATION_90, 0);
		DEFAULT_ORIENTATIONS.append(Surface.ROTATION_180, 270);
		DEFAULT_ORIENTATIONS.append(Surface.ROTATION_270, 180);
	}

	static {
		INVERSE_ORIENTATIONS.append(Surface.ROTATION_0, 270);
		INVERSE_ORIENTATIONS.append(Surface.ROTATION_90, 180);
		INVERSE_ORIENTATIONS.append(Surface.ROTATION_180, 90);
		INVERSE_ORIENTATIONS.append(Surface.ROTATION_270, 0);
	}

	/**
	 * An {@link AutoFitTextureView} for camera preview.
	 */
	private AutoFitTextureView mTextureView;


	/**
	 * A reference to the opened {@link android.hardware.camera2.CameraDevice}.
	 */
	private CameraDevice mCameraDevice;

	/**
	 * A reference to the current {@link android.hardware.camera2.CameraCaptureSession} for
	 * preview.
	 */
	private CameraCaptureSession mPreviewSession;

	/**
	 * {@link TextureView.SurfaceTextureListener} handles several lifecycle events on a
	 * {@link TextureView}.
	 */
	private TextureView.SurfaceTextureListener mSurfaceTextureListener
			= new TextureView.SurfaceTextureListener() {

		@Override
		public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture,
											  int width, int height) {
			openCamera(width, height);
		}

		@Override
		public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture,
												int width, int height) {
			configureTransform(width, height);
		}

		@Override
		public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
			return true;
		}

		@Override
		public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
		}

	};

	/**
	 * The {@link android.util.Size} of camera preview.
	 */
	private Size mPreviewSize;

	/**
	 * The {@link android.util.Size} of video recording.
	 */
	private Size mVideoSize;

	/**
	 * MediaRecorder
	 */
	private MediaRecorder mMediaRecorder;

	/**
	 * Whether the app is recording video now
	 */
	private boolean mIsRecordingVideo;

	/**
	 * An additional thread for running tasks that shouldn't block the UI.
	 */
	private HandlerThread mBackgroundThread;

	/**
	 * A {@link Handler} for running tasks in the background.
	 */
	private Handler mBackgroundHandler;

	/**
	 * A {@link Semaphore} to prevent the app from exiting before closing the camera.
	 */
	private Semaphore mCameraOpenCloseLock = new Semaphore(1);

	/**
	 * {@link CameraDevice.StateCallback} is called when {@link CameraDevice} changes its status.
	 */
	private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {

		@Override
		public void onOpened(@NonNull CameraDevice cameraDevice) {
			mCameraDevice = cameraDevice;
			do_startPreview();
			mCameraOpenCloseLock.release();
			if (null != mTextureView) {
				configureTransform(mTextureView.getWidth(), mTextureView.getHeight());
			}
		}

		@Override
		public void onDisconnected(@NonNull CameraDevice cameraDevice) {
			mCameraOpenCloseLock.release();
			cameraDevice.close();
			mCameraDevice = null;
		}

		@Override
		public void onError(@NonNull CameraDevice cameraDevice, int error) {
			mCameraOpenCloseLock.release();
			cameraDevice.close();
			mCameraDevice = null;
			// ??
		}

	};
	private Integer mSensorOrientation;
	private String mNextVideoAbsolutePath;
	private CaptureRequest.Builder mPreviewBuilder;

	private static Camera camera;
	private boolean mFlashMode;
	private int mCamerafacing;
	private String cameraId;

	public static Camera newInstance() {
		if (camera == null) {
			camera = new Camera();
		}
		return camera;
	}

	/**
	 * In this sample, we choose a video size with 3x4 aspect ratio. Also, we don't use sizes
	 * larger than 1080p, since MediaRecorder cannot handle such a high-resolution video.
	 *
	 * @param choices The list of available sizes
	 * @return The video size
	 */
	private static Size chooseVideoSize(Size[] choices) {
		for (Size size : choices) {
			if (size.getWidth() == size.getHeight() * 4 / 3 && size.getWidth() <= 1080) {
				return size;
			}
		}
		Log.e(TAG, "Couldn't find any suitable video size");
		return choices[choices.length - 1];
	}

	/**
	 * Given {@code choices} of {@code Size}s supported by a camera, chooses the smallest one whose
	 * width and height are at least as large as the respective requested values, and whose aspect
	 * ratio matches with the specified value.
	 *
	 * @param choices     The list of sizes that the camera supports for the intended output class
	 * @param width       The minimum desired width
	 * @param height      The minimum desired height
	 * @param aspectRatio The aspect ratio
	 * @return The optimal {@code Size}, or an arbitrary one if none were big enough
	 */
	private static Size chooseOptimalSize(Size[] choices, int width, int height, Size aspectRatio) {
		// Collect the supported resolutions that are at least as big as the preview Surface
		List<Size> bigEnough = new ArrayList<>();
		int w = aspectRatio.getWidth();
		int h = aspectRatio.getHeight();
		for (Size option : choices) {
			if (option.getHeight() == option.getWidth() * h / w &&
					option.getWidth() >= width && option.getHeight() >= height) {
				bigEnough.add(option);
			}
		}

		// Pick the smallest of those, assuming we found any
		if (bigEnough.size() > 0) {
			return Collections.min(bigEnough, new CompareSizesByArea());
		} else {
			Log.e(TAG, "Couldn't find any suitable preview size");
			return choices[0];
		}
	}

	public void onResume() {

		startBackgroundThread();
		if (mTextureView.isAvailable()) {
			openCamera(mTextureView.getWidth(), mTextureView.getHeight());
		} else {
			mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
		}
	}


	public void onPause() {
		closeCamera();
		stopBackgroundThread();

	}


	/**
	 * Starts a background thread and its {@link Handler}.
	 */
	private void startBackgroundThread() {
		mBackgroundThread = new HandlerThread("CameraBackground");
		mBackgroundThread.start();
		mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
	}

	/**
	 * Stops the background thread and its {@link Handler}.
	 */
	private void stopBackgroundThread() {
		mBackgroundThread.quitSafely();
		try {
			mBackgroundThread.join();
			mBackgroundThread = null;
			mBackgroundHandler = null;
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Tries to open a {@link CameraDevice}. The result is listened by `mStateCallback`.
	 */
	@SuppressWarnings("MissingPermission")
	private void openCamera(int width, int height) {

		CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
		try {
			Log.d(TAG, "tryAcquire");
			if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
				throw new RuntimeException("Time out waiting to lock camera opening.");
			}
			cameraId = manager.getCameraIdList()[0];

			// Choose the sizes for camera preview and video recording
			CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
			StreamConfigurationMap map = characteristics
					.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
			mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
			if (map == null) {
				throw new RuntimeException("Cannot get available preview/video sizes");
			}
			mVideoSize = chooseVideoSize(map.getOutputSizes(MediaRecorder.class));
			mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
					width, height, mVideoSize);

			int orientation = activity.getResources().getConfiguration().orientation;
			mHandler.sendEmptyMessage(orientation == Configuration.ORIENTATION_LANDSCAPE ? 0 : 1);
			configureTransform(width, height);

			do_openCamera();
		} catch (CameraAccessException e) {
			Toast.makeText(activity, "Cannot access the camera.", Toast.LENGTH_SHORT).show();
			activity.finish();
		} catch (NullPointerException e) {
			// Currently an NPE is thrown when the Camera2API is used but not supported on the
			// device this code runs.
			e.printStackTrace();
		} catch (InterruptedException e) {
			throw new RuntimeException("Interrupted while trying to lock camera opening.");
		}
	}

	private void do_openCamera() {
		try {
			CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);

			if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
				// TODO: Consider calling
				//    ActivityCompat#requestPermissions
				// here to request the missing permissions, and then overriding
				//   public void onRequestPermissionsResult(int requestCode, String[] permissions,
				//                                          int[] grantResults)
				// to handle the case where the user grants the permission. See the documentation
				// for ActivityCompat#requestPermissions for more details.
				return;
			}
			manager.openCamera(cameraId, mStateCallback, cameraHandler);
		} catch (CameraAccessException e) {
			Toast.makeText(activity, "Cannot access the camera.", Toast.LENGTH_SHORT).show();
			activity.finish();
		}
	}
	private void closeCamera() {
		try {
			mCameraOpenCloseLock.acquire();
			closePreviewSession();
			if (null != mCameraDevice) {
				mCameraDevice.close();
				mCameraDevice = null;
			}
			if (null != mMediaRecorder) {
				mMediaRecorder.release();
				mMediaRecorder = null;
			}
		} catch (InterruptedException e) {
			throw new RuntimeException("Interrupted while trying to lock camera closing.");
		} finally {
			mCameraOpenCloseLock.release();
		}
	}

	/**
	 * Start the camera preview.
	 */
	private void do_startPreview() {
		if (null == mCameraDevice || !mTextureView.isAvailable() || null == mPreviewSize) {
			return;
		}
		try {
			closePreviewSession();
			SurfaceTexture texture = mTextureView.getSurfaceTexture();
			assert texture != null;
			texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
			mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);

			Surface previewSurface = new Surface(texture);
			mPreviewBuilder.addTarget(previewSurface);

			mCameraDevice.createCaptureSession(Collections.singletonList(previewSurface),
					new CameraCaptureSession.StateCallback() {

						@Override
						public void onConfigured(@NonNull CameraCaptureSession session) {
							mPreviewSession = session;
							updatePreview();
						}

						@Override
						public void onConfigureFailed(@NonNull CameraCaptureSession session) {

								Toast.makeText(activity, "Failed", Toast.LENGTH_SHORT).show();

						}
					}, mBackgroundHandler);
		} catch (CameraAccessException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Update the camera preview. {@link #do_startPreview()} needs to be called in advance.
	 */
	private void updatePreview() {
		if (null == mCameraDevice) {
			return;
		}
		try {
			setUpCaptureRequestBuilder(mPreviewBuilder);
			HandlerThread thread = new HandlerThread("CameraPreview");
			thread.start();
			mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), null, mBackgroundHandler);
		} catch (CameraAccessException e) {
			e.printStackTrace();
		}
	}

	private void setUpCaptureRequestBuilder(CaptureRequest.Builder builder) {
		builder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
	}

	/**
	 * Configures the necessary {@link android.graphics.Matrix} transformation to `mTextureView`.
	 * This method should not to be called until the camera preview size is determined in
	 * openCamera, or until the size of `mTextureView` is fixed.
	 *
	 * @param viewWidth  The width of `mTextureView`
	 * @param viewHeight The height of `mTextureView`
	 */
	private void configureTransform(int viewWidth, int viewHeight) {

		if (null == mTextureView || null == mPreviewSize || null == activity) {
			return;
		}
		int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
		Matrix matrix = new Matrix();
		RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
		RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth());
		float centerX = viewRect.centerX();
		float centerY = viewRect.centerY();
		if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
			bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
			matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
			float scale = Math.max(
					(float) viewHeight / mPreviewSize.getHeight(),
					(float) viewWidth / mPreviewSize.getWidth());
			matrix.postScale(scale, scale, centerX, centerY);
			matrix.postRotate(90 * (rotation - 2), centerX, centerY);
		}
		mTextureView.setTransform(matrix);
	}

	public  void setUpMediaRecorder()  {
		if (null == activity) {
			return;
		}

		try {
			mMediaRecorder = new MediaRecorder();
			mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
			mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
			mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_2_TS);
			//File dir = activity.getExternalFilesDir(null);
			//String mVideoFilename= dir.getAbsolutePath() + "/"+"test.mp4";
            //Log.d(TAG,mVideoFilename);
			//mMediaRecorder.setOutputFile(mVideoFilename);
			mMediaRecorder.setOutputFile(fd);
			mMediaRecorder.setVideoEncodingBitRate(500000);
			mMediaRecorder.setVideoFrameRate(20);
			mMediaRecorder.setVideoSize(mVideoSize.getWidth(), mVideoSize.getHeight());
			//mMediaRecorder.setVideoSize(640,480);

			mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
			mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
			mMediaRecorder.setAudioChannels(1);
			int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
			switch (mSensorOrientation) {
				case SENSOR_ORIENTATION_DEFAULT_DEGREES:
					mMediaRecorder.setOrientationHint(DEFAULT_ORIENTATIONS.get(rotation));
					break;
				case SENSOR_ORIENTATION_INVERSE_DEGREES:
					mMediaRecorder.setOrientationHint(INVERSE_ORIENTATIONS.get(rotation));
					break;
			}
			mMediaRecorder.setMaxDuration(-1);
			mMediaRecorder.prepare();

		}catch( IOException e){
			e.printStackTrace();
		}
	}



	public  void startRecordingVideo() {
		if (null == mCameraDevice || !mTextureView.isAvailable() || null == mPreviewSize) {
			return;
		}
		try {
			closePreviewSession();
			setUpMediaRecorder();
			SurfaceTexture texture = mTextureView.getSurfaceTexture();
			assert texture != null;
			texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
			mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
			List<Surface> surfaces = new ArrayList<>();

			// Set up Surface for the camera preview
			Surface previewSurface = new Surface(texture);
			surfaces.add(previewSurface);
			mPreviewBuilder.addTarget(previewSurface);

			// Set up Surface for the MediaRecorder
			Surface recorderSurface = mMediaRecorder.getSurface();
			surfaces.add(recorderSurface);
			mPreviewBuilder.addTarget(recorderSurface);

			// Start a capture session
			// Once the session starts, we can update the UI and start recording
			mCameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {

				@Override
				public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
					mPreviewSession = cameraCaptureSession;
					updatePreview();
					activity.runOnUiThread(new Runnable() {
						@Override
						public void run() {
							// UI
							mIsRecordingVideo = true;

							// Start recording
							try {
								mMediaRecorder.start();
							}catch (IllegalStateException e) {
							    e.printStackTrace();
							}
						}
					});
				}

				@Override
				public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
					if (null != activity) {
						Toast.makeText(activity, "Failed", Toast.LENGTH_SHORT).show();
					}
				}
			}, mBackgroundHandler);
		} catch (CameraAccessException  e) {
			e.printStackTrace();
		}

	}

	private void closePreviewSession() {
		if (mPreviewSession != null) {
			mPreviewSession.close();
			mPreviewSession = null;
		}
	}

	private void stopRecordingVideo() {
		// UI
		mIsRecordingVideo = false;
		// Stop recording
		mMediaRecorder.stop();
		mMediaRecorder.reset();

		do_startPreview();
	}

	public Camera setUiActivity(SpydroidActivity ac) {
		activity=ac;
	    return this;
	}

	/**
	 * Compares two {@code Size}s based on their areas.
	 */
	static class CompareSizesByArea implements Comparator<Size> {

		@Override
		public int compare(Size lhs, Size rhs) {
			// We cast here to ensure the multiplications won't overflow
			return Long.signum((long) lhs.getWidth() * lhs.getHeight() -
					(long) rhs.getWidth() * rhs.getHeight());
		}

	}





	public  Camera open(int cameraFacing)
	{
		//openCamera(mTextureView.getWidth(),mTextureView.getHeight());
		mCamerafacing = cameraFacing;
		cameraId = getCameraId(cameraFacing);
		return this;
	}

	private String getCameraId(int cameraFacing) {
		try {
			CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
			for(final String cameraId : manager.getCameraIdList()) {
				CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
				int facing = characteristics.get(CameraCharacteristics.LENS_FACING);
				if (facing == cameraFacing) return cameraId;
			}
		} catch (CameraAccessException e) {
			e.printStackTrace();
		}
		return "0";
	}


	public interface ErrorCallback
	{
		public void onError(int error, Camera camera) ;
	};
	
	public interface PreviewCallback
	{
		public void onPreviewFrame(byte[] data, Camera camera);
	}
	
    public void setPreviewCallback( PreviewCallback cb)
	{
	}
	public void setErrorCallback( ErrorCallback cb)
	{
	}	

	public void release(){}
	public void reconnect(){}
	public void unlock(){}
	

	public MediaRecorder getMediaRecorder(){return  mMediaRecorder;}

	public Parameters getParameters()
	{
		return parameters;
	}
	public void setParameters(Parameters  p) //throws IOException
	{
		parameters=p;
	}
	public void setDisplayOrientation(int o)
	{
	}

		/**	Represents a quality for a video stream. */ 
	public Camera setTextureView( AutoFitTextureView tv) {

		mTextureView = tv;
		return this;
	}	
	public static int CAMERA_ERROR_SERVER_DIED=0;
	private static Camera instance;
	public static Camera getInstance() {
		if(instance==null){
			instance = new Camera();
		}
		return instance;
	}

	public Activity activity;


	public   int getNumbersOfCameras(){
        CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);

        if (manager == null) {
            Log.e(TAG, "selectCamera: CameraManager is null");

        }
        try {
            String[] cameraIdList = manager.getCameraIdList();   
            return cameraIdList.length;
	    } catch (CameraAccessException e) {
            e.printStackTrace();
        }
	   return 0;
    }

	public void setFlashMode(boolean mode)  {
		mFlashMode=mode;
	}



    public class Parameters {
		public static final int FLASH_MODE_OFF = 0;
		public static final int  FLASH_MODE_TORCH = 1;
		private Size videoSize;
	    private int framerate;
	    private  int flashmode;

		public void setPreviewFormat(int yv12) {
		}

		public void setPreviewSize(int resX, int resY) {
		}

		public void setPreviewFrameRate(int framerate) {
		}

		public Integer getFlashMode() {
			return (Integer)flashmode;
		}

		public void setFlashMode(int m) {
			flashmode=m;
		}

		public List<Size> getSupportedPreviewSizes() {
			try {
				CameraManager manager = (CameraManager)activity.getSystemService(Context.CAMERA_SERVICE);
				String []IdList = manager.getCameraIdList();
				String cameraId = IdList[0];
				CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
				StreamConfigurationMap scmap = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
				Size previewSizes[] = scmap.getOutputSizes(ImageReader.class);
                return Arrays.asList(previewSizes);
			} catch(CameraAccessException ex) {
				ex.printStackTrace();
			}
			return null;
		}

		public List<Integer> getSupportedPreviewFrameRates() {
			List<Integer> rates= new ArrayList<Integer>();
			try {
				CameraManager manager = (CameraManager)activity.getSystemService(Context.CAMERA_SERVICE);
				String []IdList = manager.getCameraIdList();
				String cameraId = IdList[0];
				CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
				Range<Integer>[] fpsRanges = characteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
				for(  Range<Integer> r:fpsRanges ){
					 rates.add(r.getLower());
				}
			} catch(CameraAccessException ex) {
				ex.printStackTrace();
			}
			return rates;
		}
	}

	public void setFD(FileDescriptor f){
		fd=f;
	}
	public void startRecord(){
		//startRecordingVideo();
		mHandler.sendEmptyMessage(2);
	}
	public void stopRecord(){
		//stopRecordingVideo();
		mHandler.sendEmptyMessage(4);
	}
	public void stopPreview()
	{
		//closePreviewSession();
		mHandler.sendEmptyMessage(3);
	}
	public void startPreview()
	{
		//do_startPreview();
		mHandler.sendEmptyMessage(5);
	}
	public Camera setupUIThread() {
		HandlerThread handlerThread = new HandlerThread("MyHandlerThread");
		handlerThread.start();
		cameraHandler = new Handler(handlerThread.getLooper());

		mHandler = new Handler() {
			@SuppressLint("HandlerLeak")
			@Override
			public void handleMessage(Message msg) {
				switch (msg.what) {
					case 0:
						mTextureView.setAspectRatio(mPreviewSize.getWidth(), mPreviewSize.getHeight());
						break;
					case 1:
						mTextureView.setAspectRatio(mPreviewSize.getHeight(), mPreviewSize.getWidth());
						break;
					case 2:
						startRecordingVideo();
						break;
					case 3:
						closePreviewSession();
						break;
					case 4:
					   stopRecordingVideo();
					   break;
					case 5:
						do_startPreview();
					case 6:
						do_openCamera();
						break;
				}
			}
		};
		return this;
	}
	public String getPath(){
		File  dir = activity.getFilesDir();
		return  dir.getAbsolutePath();
	}
	private Thread mThread;
	private Parameters parameters;
	private Handler mHandler;
	private Handler cameraHandler;
	private FileDescriptor fd;
};